﻿/* 
 * Copyright (c) Intel Corporation
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * -- Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * -- Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * -- Neither the name of the Intel Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Nwc.XmlRpc;
using ExtensionLoader;
using ExtensionLoader.Config;
using HttpServer;
using OpenMetaverse;
using OpenMetaverse.Http;
using OpenMetaverse.StructuredData;
using CableBeachMessages;
using OpenSimDbLinq;

namespace WorldServer.Extensions
{
    public class OpenSimLegacy : IExtension<WorldServer>
    {
        WorldServer server;

        public OpenSimLegacy()
        {
        }

        public bool Start(WorldServer server)
        {
            this.server = server;

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_grid_info", GridInfoHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "region_startup", RegionStartupHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "region_shutdown", RegionShutdownHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "agent_location", AgentLocationHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "agent_leaving", AgentLeavingHandler);
            
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "register_messageserver", RegisterMessageServerHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "agent_change_region", AgentChangeRegionHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "deregister_messageserver", DeregisterMessageServerHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "set_login_params", SetLoginParamsHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "check_auth_session", CheckAuthSessionHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_user_by_name", GetUserMethodNameHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_user_by_uuid", GetUserMethodUUIDHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_avatar_picker_avatar", GetAvatarPickerHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "update_user_current_region", UpdateUserCurrentRegionHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "logout_of_simulator", LogOffUserHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_agent_by_uuid", GetAgentUUIDHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "update_user_profile", UpdateUserProfileHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_avatar_appearance", GetAvatarAppearanceHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "update_avatar_appearance", UpdateAvatarAppearanceHandler);

            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "add_new_user_friend", AddUserFriendHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "remove_user_friend", RemoveUserFriendHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "update_user_friend_perms", UpdateUserFriendPermsHandler);
            server.XmlRpcProvider.AddXmlRpcHandler(@"^/$", "get_user_friend_list", GetUserFriendListHandler);

            //server.HttpServer.AddHandler("GET", null, @"^/users/", RestGetUserProfileHandler);
            //server.HttpServer.AddHandler("DELETE", null, @"^/usersessions/", RestDeleteUserSessionHandler);

            return true;
        }

        public void Stop()
        {
        }

        private XmlRpcResponse GridInfoHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GridInfoHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse RegionStartupHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] RegionStartupHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse RegionShutdownHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] RegionShutdownHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse AgentLocationHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] AgentLocationHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse AgentLeavingHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] AgentLeavingHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse RegisterMessageServerHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] RegisterMessageServerHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse AgentChangeRegionHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] AgentChangeRegionHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse DeregisterMessageServerHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] DeregisterMessageServerHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse SetLoginParamsHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] SetLoginParamsHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse CheckAuthSessionHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] CheckAuthSessionHandler()");

            Hashtable requestData = (Hashtable)request.Params[0];
            Hashtable responseData = new Hashtable();
            XmlRpcResponse response = new XmlRpcResponse();
            bool authed = false;

            if (requestData.Contains("avatar_uuid") && requestData.Contains("session_id"))
            {
                UUID avatarID;
                UUID sessionID;

                UUID.TryParse((string)requestData["avatar_uuid"], out avatarID);
                UUID.TryParse((string)requestData["session_id"], out sessionID);

                if (avatarID != UUID.Zero && sessionID != UUID.Zero)
                {
                    Uri identity = server.AttributeProvider.UUIDToIdentity(avatarID);

                    if (identity != null)
                    {
                        UUID currentSessionID;
                        server.SessionProvider.TryGetSession(identity, out currentSessionID);
                        authed = (sessionID == currentSessionID);
                    }
                    else
                    {
                        Logger.Warn("[OpenSimLegacy] Couldn't resolve avatarID " + avatarID + " to an identity URI");
                    }
                }
            }

            responseData["auth_session"] = (authed ? "TRUE" : "FALSE");
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse GetUserMethodNameHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GetUserMethodNameHandler()");

            Hashtable requestData = (Hashtable)request.Params[0];
            Hashtable responseData = new Hashtable();
            XmlRpcResponse response = new XmlRpcResponse();

            if (requestData.Contains("avatar_name"))
            {
                string query = requestData["avatar_name"] as string;

                if (!String.IsNullOrEmpty(query))
                {
                    string[] querySplit = query.Split(' ');

                    if (querySplit.Length == 2)
                    {
                        string firstName = querySplit[0];
                        string lastName = querySplit[1];

                        Uri identity = NameToLocalIdentity(querySplit[0], querySplit[1]);
                        Dictionary<Uri, OSD> attributes = server.AttributeProvider.GetAttributes(identity);

                        if (attributes != null)
                        {
                            responseData = AttributesToXmlRpc(attributes);
                            responseData["firstname"] = firstName;
                            responseData["lastname"] = lastName;

                            response.Value = responseData;
                            return response;
                        }
                    }
                }
            }

            responseData["error_type"] = "unknown_user";
            responseData["error_desc"] = "The user requested is not in the database";
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse GetUserMethodUUIDHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GetUserMethodUUIDHandler()");

            Hashtable requestData = (Hashtable)request.Params[0];
            Hashtable responseData = new Hashtable();
            XmlRpcResponse response = new XmlRpcResponse();

            if (requestData.Contains("avatar_uuid"))
            {
                UUID queryID;
                if (UUID.TryParse(requestData["avatar_uuid"] as string, out queryID))
                {
                    Uri identity = server.AttributeProvider.UUIDToIdentity(queryID);
                    Dictionary<Uri, OSD> attributes = server.AttributeProvider.GetAttributes(identity);

                    if (attributes != null)
                    {
                        responseData = AttributesToXmlRpc(attributes);
                        responseData["uuid"] = queryID;

                        response.Value = responseData;
                        return response;
                    }
                }
            }

            responseData["error_type"] = "unknown_user";
            responseData["error_desc"] = "The user requested is not in the database";
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse GetAvatarPickerHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GetAvatarPickerHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse UpdateUserCurrentRegionHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] UpdateUserCurrentRegionHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse LogOffUserHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] LogOffUserHandler()");

            Hashtable requestData = (Hashtable)request.Params[0];
            Hashtable responseData = new Hashtable();
            XmlRpcResponse response = new XmlRpcResponse();

            if (requestData.Contains("avatar_uuid"))
            {
                UUID avatarID;
                UUID.TryParse(requestData["avatar_uuid"] as string, out avatarID);
                UUID regionID;
                UUID.TryParse(requestData["region_uuid"] as string, out regionID);
                ulong regionHandle = Convert.ToUInt64(requestData["region_handle"] as string);
                uint regionX, regionY;
                Utils.LongToUInts(regionHandle, out regionX, out regionY);
                regionX /= 256;
                regionY /= 256;

                // Parsing caused expections so let do some checking first
                string region_x = requestData["region_pos_x"].ToString();
                if (region_x.Contains("."))
                    region_x = region_x.Substring(0, region_x.IndexOf("."));
                string region_y = requestData["region_pos_y"].ToString();
                if (region_y.Contains("."))
                    region_y = region_y.Substring(0, region_y.IndexOf("."));
                string region_z = requestData["region_pos_z"].ToString();
                if (region_z.Contains("."))
                    region_z = region_z.Substring(0, region_z.IndexOf("."));
                Vector3 position = new Vector3(
                    Convert.ToSingle(region_x),
                    Convert.ToSingle(region_y),
                    Convert.ToSingle(region_z));

                // Parsing caused expections so let do some checking first
                string look_x = requestData["lookat_x"].ToString();
                if (look_x.Contains("."))
                    look_x = look_x.Substring(0, look_x.IndexOf("."));
                string look_y = requestData["lookat_y"].ToString();
                if (look_y.Contains("."))
                    look_y = look_y.Substring(0, look_y.IndexOf("."));
                string look_z = requestData["lookat_z"].ToString();
                if (look_z.Contains("."))
                    look_z = look_z.Substring(0, look_z.IndexOf("."));
                Vector3 lookAt = new Vector3(
                    Convert.ToSingle(look_x),
                    Convert.ToSingle(look_y),
                    Convert.ToSingle(look_z));

                Uri identity = server.AttributeProvider.UUIDToIdentity(avatarID);

                if (identity != null)
                {
                    Dictionary<Uri, OSD> attributes = server.AttributeProvider.GetAttributes(identity);
                    if (attributes != null)
                    {
                        attributes[AvatarAttributes.LAST_LOOKAT] = OSD.FromVector3(lookAt);
                        attributes[AvatarAttributes.LAST_POSITION] = OSD.FromVector3(position);
                        attributes[AvatarAttributes.LAST_REGION_ID] = OSD.FromUUID(regionID);
                        attributes[AvatarAttributes.LAST_REGION_X] = OSD.FromUInteger(regionX);
                        attributes[AvatarAttributes.LAST_REGION_Y] = OSD.FromUInteger(regionY);

                        server.AttributeProvider.UpdateAttributes(identity, attributes);
                    }

                    server.SessionProvider.RemoveSession(identity);
                }
            }
            else
            {
                responseData["error_type"] = "unknown_user";
                responseData["error_desc"] = "The user requested is not in the database";
            }

            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse GetAgentUUIDHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GetAgentUUIDHandler()");

            Hashtable requestData = (Hashtable)request.Params[0];
            Hashtable responseData = new Hashtable();
            XmlRpcResponse response = new XmlRpcResponse();

            if (requestData.Contains("avatar_uuid"))
            {
                string avatarIDString = requestData["avatar_uuid"] as string;
                UUID avatarID;

                if (!String.IsNullOrEmpty(avatarIDString) && UUID.TryParse(avatarIDString, out avatarID))
                {
                    Uri identity = server.AttributeProvider.UUIDToIdentity(avatarID);
                    UUID authToken;
                    Avatar avatar;

                    if (identity != null &&
                        server.SessionProvider.TryGetSession(identity, out authToken) &&
                        server.SessionProvider.TryGetAvatar(authToken, out avatar))
                    {
                        // FIXME: Finish this
                    }
                }
            }

            responseData["error_type"] = "unknown_user";
            responseData["error_desc"] = "The user requested is not in the database";
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse UpdateUserProfileHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] UpdateUserProfileHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse GetAvatarAppearanceHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GetAvatarAppearanceHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse UpdateAvatarAppearanceHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] UpdateAvatarAppearanceHandler()");

            Hashtable requestData = (Hashtable)request.Params[0];
            Hashtable responseData = new Hashtable();
            XmlRpcResponse response = new XmlRpcResponse();

            if (requestData.Contains("owner"))
            {
                UUID avatarID = new UUID(requestData["owner"] as string);
                Uri identity = server.AttributeProvider.UUIDToIdentity(avatarID);

                if (identity != null)
                {
                    Dictionary<Uri, OSD> attributes = server.AttributeProvider.GetAttributes(identity);

                    if (attributes != null)
                    {
                        int serial = Convert.ToInt32(requestData["serial"] as string);
                        attributes[AvatarAttributes.VISUAL_PARAMS] = OSD.FromBinary(requestData["visual_params"] as byte[]);
                        attributes[AvatarAttributes.TEXTURE_ENTRY] = OSD.FromBinary(requestData["texture"] as byte[]);
                        attributes[AvatarAttributes.AVATAR_HEIGHT] = OSD.FromReal(Convert.ToSingle(requestData["avatar_height"] as string));
                        // FIXME: Finish this

                        server.AttributeProvider.UpdateAttributes(identity, attributes);

                        responseData["returnString"] = "TRUE";
                        response.Value = responseData;
                        return response;
                    }
                }
            }

            responseData["error_type"] = "unknown_avatar";
            responseData["error_desc"] = "The avatar appearance requested is not in the database";
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse AddUserFriendHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] AddUserFriendHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse RemoveUserFriendHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] RemoveUserFriendHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse UpdateUserFriendPermsHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] UpdateUserFriendPermsHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        private XmlRpcResponse GetUserFriendListHandler(XmlRpcRequest request, IHttpRequest httpRequest)
        {
            Logger.Debug("[OpenSimLegacy] GetUserFriendListHandler()");

            Hashtable responseData = new Hashtable();

            XmlRpcResponse response = new XmlRpcResponse();
            response.Value = responseData;
            return response;
        }

        #region Helper Methods

        private string GetAttributeString(Uri attributeIdentifier, Dictionary<Uri, OSD> attributes)
        {
            OSD value;
            if (attributes.TryGetValue(attributeIdentifier, out value))
                return value.AsString();
            else
                return String.Empty;
        }

        private Vector3 GetAttributeVector3(Uri attributeIdentifier, Dictionary<Uri, OSD> attributes)
        {
            OSD value;
            if (attributes.TryGetValue(attributeIdentifier, out value))
                return value.AsVector3();
            else
                return Vector3.Zero;
        }

        private uint GetAttributeUInt(Uri attributeIdentifier, Dictionary<Uri, OSD> attributes)
        {
            OSD value;
            if (attributes.TryGetValue(attributeIdentifier, out value))
                return value.AsUInteger();
            else
                return 0;
        }

        private UUID GetAttributeUUID(Uri attributeIdentifier, Dictionary<Uri, OSD> attributes)
        {
            OSD value;
            if (attributes.TryGetValue(attributeIdentifier, out value))
                return value.AsUUID();
            else
                return UUID.Zero;
        }

        private Uri NameToLocalIdentity(string firstName, string lastName)
        {
            return new Uri(server.HttpUri, "/users/" + firstName + "." + lastName);
        }

        private Hashtable AttributesToXmlRpc(Dictionary<Uri, OSD> attributes)
        {
            Hashtable responseData = new Hashtable();

            // Account information
            responseData["firstname"] = GetAttributeString(AvatarAttributes.FIRST_NAME, attributes);
            responseData["lastname"] = GetAttributeString(AvatarAttributes.LAST_NAME, attributes);
            responseData["uuid"] = GetAttributeUUID(AvatarAttributes.AVATAR_ID, attributes).ToString();

            // Server Information. Cable Beach service capabilities are passed around with the login
            // session data, and are not accessible through a profile fetch
            responseData["server_inventory"] = String.Empty;
            responseData["server_asset"] = String.Empty;

            // Profile Information
            responseData["profile_about"] = GetAttributeString(AvatarAttributes.BIOGRAPHY, attributes);
            responseData["profile_firstlife_about"] = GetAttributeUUID(AvatarAttributes.FIRST_LIFE_BIOGRAPHY, attributes).ToString();
            responseData["profile_firstlife_image"] = GetAttributeUUID(AvatarAttributes.FIRST_LIFE_IMAGE_ID, attributes).ToString();
            responseData["profile_can_do"] = GetAttributeUInt(AvatarAttributes.CAN_DO, attributes).ToString();
            responseData["profile_want_do"] = GetAttributeUInt(AvatarAttributes.WANT_DO, attributes).ToString();
            responseData["profile_image"] = GetAttributeUUID(AvatarAttributes.IMAGE_ID, attributes).ToString();
            responseData["profile_created"] = GetAttributeUInt(AvatarAttributes.BIRTH_DATE, attributes).ToString();
            responseData["profile_lastlogin"] = GetAttributeUInt(AvatarAttributes.LAST_LOGIN_DATE, attributes).ToString();

            // Home region information
            Vector3 homePosition = GetAttributeVector3(AvatarAttributes.HOME_POSITION, attributes);
            responseData["home_coordinates_x"] = homePosition.X.ToString();
            responseData["home_coordinates_y"] = homePosition.Y.ToString();
            responseData["home_coordinates_z"] = homePosition.Z.ToString();
            ulong homeRegionHandle = Utils.UIntsToLong(
                GetAttributeUInt(AvatarAttributes.HOME_REGION_X, attributes),
                GetAttributeUInt(AvatarAttributes.HOME_REGION_X, attributes));
            responseData["home_region"] = homeRegionHandle.ToString();
            responseData["home_region_id"] = GetAttributeUUID(AvatarAttributes.HOME_REGION_ID, attributes).ToString();
            Vector3 homeLookAt = GetAttributeVector3(AvatarAttributes.HOME_LOOKAT, attributes);
            responseData["home_look_x"] = homeLookAt.X.ToString();
            responseData["home_look_y"] = homeLookAt.Y.ToString();
            responseData["home_look_z"] = homeLookAt.Z.ToString();

            // Miscellaneous
            responseData["user_flags"] = GetAttributeUInt(AvatarAttributes.USER_FLAGS, attributes).ToString();
            responseData["god_level"] = GetAttributeUInt(AvatarAttributes.GOD_LEVEL, attributes).ToString();
            responseData["custom_type"] = GetAttributeString(AvatarAttributes.CUSTOM_TYPE, attributes);
            responseData["partner"] = GetAttributeUUID(AvatarAttributes.PARTNER_ID, attributes).ToString();

            return responseData;
        }

        #endregion Helper Methods
    }
}
